home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / xmesa3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-03  |  16.7 KB  |  571 lines

  1. /* $Id: xmesa3.c,v 1.7 1995/11/30 00:21:36 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Log: xmesa3.c,v $
  26.  * Revision 1.7  1995/11/30  00:21:36  brianp
  27.  * added PF_GRAYSCALE support
  28.  *
  29.  * Revision 1.6  1995/11/14  21:49:09  brianp
  30.  * optimized polygon rendering setup
  31.  *
  32.  * Revision 1.5  1995/11/08  22:08:22  brianp
  33.  * fixed OFFSET4/1 bug in smooth_rgba_z_polygon_ximage()
  34.  *
  35.  * Revision 1.4  1995/11/04  20:09:32  brianp
  36.  * added F suffix to floating point constants
  37.  * replaced incorrect 0.05F with 0.5F
  38.  *
  39.  * Revision 1.3  1995/11/03  17:41:48  brianp
  40.  * removed unused vars, fixed code for C++ compilation
  41.  *
  42.  * Revision 1.2  1995/10/30  15:50:41  brianp
  43.  * make sure CC.ClipSpans is FALSE before using smooth_rgba_z_polygon_ximage
  44.  *
  45.  * Revision 1.1  1995/10/30  15:15:15  brianp
  46.  * Initial revision
  47.  *
  48.  */
  49.  
  50.  
  51. /*
  52.  * Mesa/X11 interface, part 3.
  53.  *
  54.  * This file contains "accelerated" point, line, and polygon functions.
  55.  * It should be fairly easy to write new special-purpose point, line or
  56.  * polygon functions and hook them into this module.
  57.  */
  58.  
  59.  
  60.  
  61. #include <stdlib.h>
  62. #include <stdio.h>
  63. #include "X11/Xlib.h"
  64. #include "context.h"
  65. #include "dd.h"
  66. #include "interp.h"
  67. #include "macros.h"
  68. #include "polygons.h"
  69. #include "vb.h"
  70. #include "xmesaP.h"
  71.  
  72. /*
  73.  * Given a vertex number return an X pixel value.
  74.  */
  75. static unsigned long encode_color( GLuint i )
  76. {
  77.    switch (XMesa->pixelformat) {
  78.       case PF_INDEX:
  79.          return (unsigned long) VB.Index[i];
  80.       case PF_TRUECOLOR:
  81.          {
  82.             register int r, g, b;
  83.             r = VB.Color[i][0] * CC.RedScale;
  84.             g = VB.Color[i][1] * CC.GreenScale;
  85.             b = VB.Color[i][2] * CC.BlueScale;
  86.             return PACK_RGB( r, g, b );
  87.          }
  88.       case PF_8A8B8G8R:
  89.          {
  90.             register int r, g, b, a;
  91.             r = VB.Color[i][0] * 255.0F;
  92.             g = VB.Color[i][1] * 255.0F;
  93.             b = VB.Color[i][2] * 255.0F;
  94.             a = VB.Color[i][3] * 255.0F;
  95.             return (a << 24) | (b << 16) | (g << 8) | r;
  96.          }
  97.       case PF_DITHER:
  98.          {
  99.             register int r, g, b;
  100.             r = VB.Color[i][0] * 255.0F;
  101.             g = VB.Color[i][1] * 255.0F;
  102.             b = VB.Color[i][2] * 255.0F;
  103.             return DITHER_8BIT( 0, 0, r, g, b );
  104.          }
  105.       case PF_1BIT:
  106.          {
  107.             register int r, g, b;
  108.             r = VB.Color[i][0] * 255.0F;
  109.             g = VB.Color[i][1] * 255.0F;
  110.             b = VB.Color[i][2] * 255.0F;
  111.             return (r+g+b) > 382;
  112.          }
  113.       case PF_HPCR:
  114.          {
  115.             register int r, g, b;
  116.             r = VB.Color[i][0] * 255.0F;
  117.             g = VB.Color[i][1] * 255.0F;
  118.             b = VB.Color[i][2] * 255.0F;
  119.             return DITHER_HPCR( 1, 1, r, g, b );
  120.          }
  121.       case PF_LOOKUP:
  122.          {
  123.             register int r, g, b;
  124.             r = VB.Color[i][0] * 255.0F;
  125.             g = VB.Color[i][1] * 255.0F;
  126.             b = VB.Color[i][2] * 255.0F;
  127.             return LOOKUP( r, g, b );
  128.          }
  129.       case PF_GRAYSCALE:
  130.          {
  131.             register int r, g, b;
  132.             r = VB.Color[i][0] * CC.RedScale;
  133.             g = VB.Color[i][1] * CC.GreenScale;
  134.             b = VB.Color[i][2] * CC.BlueScale;
  135.             return GRAY_RGB( r, g, b );
  136.          }
  137.       default:
  138.          abort();
  139.    }
  140.    return 0;
  141. }
  142.  
  143.  
  144.  
  145. /**********************************************************************/
  146. /***                    Point rendering                             ***/
  147. /**********************************************************************/
  148.  
  149.  
  150. /*
  151.  * Render an array of points into a pixmap, any pixel format.
  152.  */
  153. static void draw_points_ANY_pixmap( GLuint first, GLuint last )
  154. {
  155.    register GLuint i;
  156.    if (VB.MonoColor) {
  157.       /* all same color */
  158.       XPoint p[VB_SIZE];
  159.       int n = 0;
  160.       for (i=first;i<=last;i++) {
  161.          if (VB.Unclipped[i]) {
  162.             p[n].x =       (GLint) (VB.Win[i][0] + 0.5F);
  163.             p[n].y = FLIP( (GLint) (VB.Win[i][1] + 0.5F) );
  164.             n++;
  165.          }
  166.       }
  167.       XDrawPoints( XMesa->display, XMesa->buffer, XMesa->gc1, p, n,
  168.                    CoordModeOrigin );
  169.    }
  170.    else {
  171.       /* all different colors */
  172.       for (i=first;i<=last;i++) {
  173.          if (VB.Unclipped[i]) {
  174.             register int x, y;
  175.             XSetForeground( XMesa->display, XMesa->gc2, encode_color(i) );
  176.             x =       (GLint) (VB.Win[i][0] + 0.5F);
  177.             y = FLIP( (GLint) (VB.Win[i][1] + 0.5F) );
  178.             XDrawPoint( XMesa->display, XMesa->buffer, XMesa->gc2, x, y);
  179.          }
  180.       }
  181.    }
  182. }
  183.  
  184.  
  185.  
  186. /*
  187.  * Analyze current CC state to see if we can provide a fast points drawing
  188.  * function, like those in points.c.  Otherwise, return NULL.
  189.  */
  190. points_func xmesa_get_points_func( void )
  191. {
  192.    if (CC.Point.Size==1.0F && !CC.Point.SmoothFlag && CC.RasterMask==0
  193.        && !CC.Texture.Enabled) {
  194.       if (XMesa->buffer==XIMAGE) {
  195.          return NULL; /*draw_points_ximage;*/
  196.       }
  197.       else {
  198.          return draw_points_ANY_pixmap;
  199.       }
  200.    }
  201.    else {
  202.       return NULL;
  203.    }
  204. }
  205.  
  206.  
  207.  
  208. /**********************************************************************/
  209. /***                      Line rendering                            ***/
  210. /**********************************************************************/
  211.  
  212. /*
  213.  * Render a line into a pixmap, any pixel format.
  214.  */
  215. static void draw_line_ANY_pixmap( GLuint v0, GLuint v1, GLuint pv )
  216. {
  217.    register int x0, y0, x1, y1;
  218.    GC gc;
  219.    if (VB.MonoColor) {
  220.       gc = XMesa->gc1;  /* use current color */
  221.    }
  222.    else {
  223.       gc = XMesa->gc2;
  224.       XSetForeground( XMesa->display, XMesa->gc2, encode_color(pv) );
  225.    }
  226.    x0 =       (GLint) (VB.Win[v0][0] + 0.5F);
  227.    y0 = FLIP( (GLint) (VB.Win[v0][1] + 0.5F) );
  228.    x1 =       (GLint) (VB.Win[v1][0] + 0.5F);
  229.    y1 = FLIP( (GLint) (VB.Win[v1][1] + 0.5F) );
  230.    XDrawLine( XMesa->display, XMesa->buffer, gc, x0, y0, x1, y1 );
  231. }
  232.  
  233.  
  234.  
  235. /*
  236.  * Analyze current CC state to see if we can provide a fast line drawing
  237.  * function, like those in lines.c.  Otherwise, return NULL.
  238.  */
  239. line_func xmesa_get_line_func( void )
  240. {
  241.    if (CC.Line.Width==1.0F && !CC.Line.SmoothFlag && !CC.Line.StippleFlag
  242.        && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
  243.        && !CC.Texture.Enabled) {
  244.       if (XMesa->buffer==XIMAGE) {
  245.          /* no Xlib func for drawing lines into ximages */
  246.          return NULL;
  247.       }
  248.       else {
  249.          return draw_line_ANY_pixmap;
  250.       }
  251.    }
  252.    else {
  253.       return NULL;
  254.    }
  255. }
  256.  
  257.  
  258.  
  259.  
  260. /**********************************************************************/
  261. /***                   Polygon rendering                            ***/
  262. /**********************************************************************/
  263.  
  264. /*
  265.  * Render a polygon into a pixmap, any pixel format.
  266.  */
  267. void draw_polygon_ANY_pixmap( GLuint n, GLuint vlist[], GLuint pv )
  268. {
  269.    GLuint i;
  270.    XPoint p[VB_SIZE];
  271.    GC gc;
  272.    if (VB.MonoColor) {
  273.       gc = XMesa->gc1;  /* use current color */
  274.    }
  275.    else {
  276.       gc = XMesa->gc2;
  277.       XSetForeground( XMesa->display, XMesa->gc2, encode_color(pv) );
  278.    }
  279.    for (i=0;i<n;i++) {
  280.       GLuint j = vlist[i];
  281.       p[i].x =       (GLint) (VB.Win[j][0] + 0.5F);
  282.       p[i].y = FLIP( (GLint) (VB.Win[j][1] + 0.5F) ) + 1;
  283.    }
  284.    XFillPolygon( XMesa->display, XMesa->buffer, gc,
  285.          p, n, Convex, CoordModeOrigin );
  286. }
  287.  
  288.  
  289.  
  290. static GLfloat flx[MAX_HEIGHT], frx[MAX_HEIGHT];/* X bounds */
  291. static GLint lr[MAX_HEIGHT], rr[MAX_HEIGHT];    /* Red */
  292. static GLint lg[MAX_HEIGHT], rg[MAX_HEIGHT];    /* Green */
  293. static GLint lb[MAX_HEIGHT], rb[MAX_HEIGHT];    /* Blue */
  294. static GLint la[MAX_HEIGHT], ra[MAX_HEIGHT];    /* Alpha */
  295.  
  296. #define EDGEMAX MAX_WIDTH
  297.  
  298.  
  299.  
  300. /*
  301.  * Render a smooth shaded, RGBA, depth-bufferd polygon into an XImage.
  302.  */
  303. void smooth_rgba_z_polygon_ximage( GLuint n, GLuint vlist[], GLuint pv )
  304. {
  305.    GLint i, j, y;
  306.    GLint ymin, ymax;
  307.  
  308.    /* find min and max of window coordinate Y values */
  309.    {
  310.       GLfloat min = 1.0e10F;
  311.       GLfloat max = -1.0e10F;
  312.       if (n==3) {
  313.          GLfloat winy;
  314.          winy = VB.Win[vlist[0]][1];
  315.          if (winy > max)  max = winy;
  316.          if (winy < min)  min = winy;
  317.          winy = VB.Win[vlist[1]][1];
  318.          if (winy > max)  max = winy;
  319.          if (winy < min)  min = winy;
  320.          winy = VB.Win[vlist[2]][1];
  321.          if (winy > max)  max = winy;
  322.          if (winy < min)  min = winy;
  323.       }
  324.       else {
  325.          for (i=0;i<n;i++) {
  326.             GLfloat winy = VB.Win[vlist[i]][1];
  327.             if (winy > max)  max = winy;
  328.             if (winy < min)  min = winy;
  329.          }
  330.       }
  331.       ymin = (GLint) min;
  332.       ymax = (GLint) max;
  333.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 );
  334.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 );
  335.    }
  336.  
  337.    /* init edge bounds */
  338.    for (y=ymin;y<=ymax;y++) {
  339.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  340.       frx[y] = -1.0F;
  341.    }
  342.  
  343.    /* process edges to compute bounds */
  344.    for (i=0;i<n;i++) {
  345.       GLuint j0, j1, len;
  346.       GLfloat ex[EDGEMAX];
  347.       GLint ey[EDGEMAX];
  348.       GLint r0, g0, b0, a0, r1, g1, b1, a1, dr, dg, db, da;
  349.  
  350.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  351.       j1 = vlist[i];
  352.  
  353.       /* compute edge pixels */
  354.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  355.                              VB.Win[j1][0], VB.Win[j1][1],
  356.                              ex, ey );
  357.  
  358.       /* interpolate colors along edge */
  359.       r0 = (GLint) (VB.Color[j0][0] * CC.RedScale) << 8;
  360.       r1 = (GLint) (VB.Color[j1][0] * CC.RedScale) << 8;
  361.       g0 = (GLint) (VB.Color[j0][1] * CC.GreenScale) << 8;
  362.       g1 = (GLint) (VB.Color[j1][1] * CC.GreenScale) << 8;
  363.       b0 = (GLint) (VB.Color[j0][2] * CC.BlueScale) << 8;
  364.       b1 = (GLint) (VB.Color[j1][2] * CC.BlueScale) << 8;
  365.       a0 = (GLint) (VB.Color[j0][3] * CC.AlphaScale) << 8;
  366.       a1 = (GLint) (VB.Color[j1][3] * CC.AlphaScale) << 8;
  367.       if (len>1) {
  368.          GLint n = len-1;
  369.          dr = (r1-r0) / n;
  370.          dg = (g1-g0) / n;
  371.          db = (b1-b0) / n;
  372.          da = (a1-a0) / n;
  373.       }
  374.       else {
  375.          dr = dg = db = da = 0;
  376.       }
  377.  
  378.       /* update span bounds */
  379.       for (j=0;j<len;j++) {
  380.      GLfloat x = ex[j];
  381.      GLint y = ey[j];
  382.      if (y>=0 && y<MAX_HEIGHT) {
  383.         if (x < flx[y]) {
  384.            flx[y] = x;
  385.            lr[y] = r0 >> 8;
  386.            lg[y] = g0 >> 8;
  387.            lb[y] = b0 >> 8;
  388.            la[y] = a0 >> 8;
  389.         }
  390.         if (x > frx[y]) {
  391.            frx[y] = x;
  392.            rr[y] = r0 >> 8;
  393.            rg[y] = g0 >> 8;
  394.            rb[y] = b0 >> 8;
  395.            ra[y] = a0 >> 8;
  396.         }
  397.      }
  398.          r0 += dr;   g0 += dg;   b0 += db;   a0 += da;
  399.       }
  400.    }
  401.  
  402.    /* process spans */
  403.    for (y=ymin;y<=ymax;y++) {
  404.       GLint xmin = (GLint) (flx[y] + 0.5F);
  405.       GLint xmax = (GLint) (frx[y] - 0.5F);
  406.       GLint len = xmax-xmin+1;
  407.       if (len>0) {
  408.      GLint z0, z1, zspan[MAX_WIDTH];
  409.          GLint *zptr = CC.DepthBuffer + y * CC.BufferWidth + xmin;
  410.          GLint r, g, b, a, dr, dg, db, da;
  411.  
  412.      /* interpolate z */
  413.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  414.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  415.      GL_INTERPOLATE_I( len, z0, z1, zspan );
  416.  
  417.          /* setup for color interpolation */
  418.          r = lr[y] << 8;
  419.          g = lg[y] << 8;
  420.          b = lb[y] << 8;
  421.          a = la[y] << 8;
  422.          if (len>1) {
  423.             dr = ((rr[y] << 8) - r) / (len-1);
  424.             dg = ((rg[y] << 8) - g) / (len-1);
  425.             db = ((rb[y] << 8) - b) / (len-1);
  426.             da = ((ra[y] << 8) - a) / (len-1);
  427.          }
  428.          else {
  429.             dr = dg = db = da = 0;
  430.          }
  431.  
  432.      /* do depth test and write interpolated pixels */
  433.          switch (XMesa->pixelformat) {
  434.             case PF_TRUECOLOR:
  435.                {
  436.                   int yy = FLIP(y);
  437.                   for (i=0;i<len;i++) {
  438.                      if (zspan[i]<zptr[i]) {
  439.                         unsigned long p;
  440.                         zptr[i] = zspan[i];
  441.                         p = PACK_RGBA( r>>8, g>>8, b>>8, a>>8 );
  442.                         XPutPixel( XMesa->backimage, xmin+i, yy, p );
  443.                      }
  444.                      r += dr;  g += dg;  b += db;  a += da;
  445.                   }
  446.                }
  447.                break;
  448.             case PF_8A8B8G8R:
  449.                {
  450.                   GLuint *img = (GLuint *) XMesa->backimage->data
  451.                                 + OFFSET4(xmin,y);
  452.                   for (i=0;i<len;i++) {
  453.                      if (zspan[i]<zptr[i]) {
  454.                         zptr[i] = zspan[i];
  455.                         img[i] = ((a << 16) & 0xff000000) |
  456.                                  ((b << 8 ) & 0x00ff0000) |
  457.                                  ((g      ) & 0x0000ff00) |
  458.                                  ((r >> 8 ) & 0x000000ff);
  459.                      }
  460.                      r += dr;  g += dg;  b += db;  a += da;
  461.                   }
  462.                }
  463.                break;
  464.             case PF_DITHER:
  465.                if (XMesa->depth==8) {
  466.                   GLubyte *img = (GLubyte *) XMesa->backimage->data
  467.                               + OFFSET1(xmin,y);
  468.                   for (i=0;i<len;i++) {
  469.                      if (zspan[i]<zptr[i]) {
  470.                         zptr[i] = zspan[i];
  471.                         img[i] = DITHER_8BIT( xmin+i, y, r>>8, g>>8, b>>8 );
  472.                      }
  473.                      r += dr;  g += dg;  b += db;
  474.                   }
  475.                }
  476.                else {
  477.                   int yy = FLIP(y);
  478.                   for (i=0;i<len;i++) {
  479.                      if (zspan[i]<zptr[i]) {
  480.                         unsigned long p;
  481.                         zptr[i] = zspan[i];
  482.                         p = DITHER_8BIT( xmin+i, y, r>>8, g>>8, b>>8 );
  483.                         XPutPixel( XMesa->backimage, xmin+i, yy, p );
  484.                      }
  485.                      r += dr;  g += dg;  b += db;
  486.                   }
  487.                }
  488.                break;
  489.             case PF_HPCR:
  490.                {
  491.                   GLubyte *img = (GLubyte *) XMesa->backimage->data
  492.                               + OFFSET1(xmin,y);
  493.                   for (i=0;i<len;i++) {
  494.                      if (zspan[i]<zptr[i]) {
  495.                         zptr[i] = zspan[i];
  496.                         img[i] = DITHER_HPCR( xmin+i, y, r>>8, g>>8, b>>8 );
  497.                      }
  498.                      r += dr;  g += dg;  b += db;
  499.                   }
  500.                }
  501.                break;
  502.             case PF_LOOKUP:
  503.                {
  504.                   int yy = FLIP(y);
  505.                   for (i=0;i<len;i++) {
  506.                      if (zspan[i]<zptr[i]) {
  507.                         unsigned long p;
  508.                         zptr[i] = zspan[i];
  509.                         p = LOOKUP( r>>8, g>>8, b>>8 );
  510.                         XPutPixel( XMesa->backimage, xmin+i, yy, p );
  511.                      }
  512.                      r += dr;  g += dg;  b += db;
  513.                   }
  514.                }
  515.             case PF_GRAYSCALE:
  516.                {
  517.                   int yy = FLIP(y);
  518.                   for (i=0;i<len;i++) {
  519.                      if (zspan[i]<zptr[i]) {
  520.                         unsigned long p;
  521.                         zptr[i] = zspan[i];
  522.                         p = GRAY_RGB( r>>8, g>>8, b>>8 );
  523.                         XPutPixel( XMesa->backimage, xmin+i, yy, p );
  524.                      }
  525.                      r += dr;  g += dg;  b += db;
  526.                   }
  527.                }
  528.                break;
  529.             default:
  530.                abort();
  531.          } /*switch*/
  532.       }
  533.    }
  534. }
  535.  
  536.  
  537.  
  538. /*
  539.  * Analyze current CC and device driver state to see if we can provide a
  540.  * fast polygon drawing function, like those in polygons.c.  Otherwise,
  541.  * return NULL.
  542.  */
  543. polygon_func xmesa_get_polygon_func( void )
  544. {
  545.    if (!CC.Polygon.SmoothFlag && !CC.Polygon.StippleFlag
  546.        && CC.Light.ShadeModel==GL_SMOOTH && CC.RasterMask==DEPTH_BIT
  547.        && CC.Depth.Func==GL_LESS && !CC.Texture.Enabled
  548.        && !CC.ClipSpans
  549.        && XMesa->buffer==XIMAGE) {
  550.       switch (XMesa->pixelformat) {
  551.          case PF_TRUECOLOR:
  552.          case PF_8A8B8G8R:
  553.          case PF_DITHER:
  554.          case PF_HPCR:
  555.          case PF_LOOKUP:
  556.          case PF_GRAYSCALE:
  557.             return smooth_rgba_z_polygon_ximage;
  558.          default:
  559.             return NULL;
  560.       }
  561.    }
  562.  
  563.    if (!CC.Polygon.SmoothFlag && !CC.Polygon.StippleFlag
  564.        && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
  565.        && !CC.Texture.Enabled && XMesa->buffer!=XIMAGE) {
  566.       return draw_polygon_ANY_pixmap;
  567.    }
  568.  
  569.    return NULL;
  570. }
  571.